package valuecomusa.fijibus.eticket.shorthaul;

import android.app.*;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Color;
//import android.nfc.NfcAdapter;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.os.*;
import android.text.Html;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.valuecomusa.Enums;
import com.valuecomusa.bmf.NfcCardInfo;
import valuecomusa.fijibus.eticket.*;
import valuecomusa.fijibus.eticket.db.shorthaul.BusinessDBHandler;
import valuecomusa.fijibus.eticket.db.shorthaul.GpsDBHandler;
import valuecomusa.fijibus.eticket.dialog.HomeWaitCard;
import valuecomusa.fijibus.eticket.dialog.refund;
import valuecomusa.fijibus.eticket.dto.GpsCurrentLocationValue;
import valuecomusa.fijibus.eticket.ws.MemberValue;
import valuecomusa.fijibus.eticket.ws.TransactionValue;

import java.util.Date;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;

import static android.widget.Toast.LENGTH_SHORT;

public class Main extends SunbeamActivity
{
    private static Activity theInstance;

    public static Activity getInstance()
    {
        return theInstance;
    }

    private int cardSlot;
    private static int counter = 1;
    private String TAG = "MAIN";
    private BusinessDBHandler db;
    private GpsDBHandler gpsDb;
    private int lastRequest = 0;

    public Main()
    {
        Main.theInstance = this;
        //--
        TAG = TAG + "." + counter++;
        if (counter > 1000000)
            counter = 1;
    }
    //private NfcCardInfo info =  new NfcCardInfo();
    //private ThreadHandlerTapCard cardTap;

    private Handler theHandler;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        Log.d(TAG, "[onCreate] ....");
        super.onCreate(savedInstanceState);
        Log.d(TAG, "[onCreate] set content view");
        setContentView(R.layout.main);
        Log.d(TAG, "[onCreate] set WorkingSession.getInstance().currentActivity = Main.this");
        WorkingSession.getInstance().currentActivity = Main.this;
        //--
        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                                           .detectNetwork() // or .detectAll() for all detectable problems
                                           .penaltyLog().build());

        Log.d(TAG, "[onCreate] Register event for home button, back, logout,... ");
        doCommon();
        //--
        theHandler = new Handler();
        //--
        Log.d(TAG, "[onCreate] WorkingSession.getInstance().setSAMReaderEventListener(samReaderEvent, false);");
        WorkingSession.getInstance().setSAMReaderEventListener(samReaderEvent, false);
        //--



//        HandlerThread  threadHandler =  new HandlerThread("ThreadHandlerTapCard");
//        threadHandler.start();
//        cardTap = new ThreadHandlerTapCard(threadHandler.getLooper());
//        Log.d(TAG, "[onCreate] setSmartCardTappedCallback");
//        WorkingSession.getInstance().setSmartCardTappedCallback(cardTap);

        //--
        Log.d(TAG, "[onCreate] create db instances");
        WorkingSession.getInstance().currentPassenger = null;
        db = new BusinessDBHandler(getApplicationContext());
        gpsDb = new GpsDBHandler(Main.this);
        //--
        Log.d(TAG, "[onCreate] Register on-screen button event");
        Button checkIn = (Button) findViewById(R.id.btCheckIn);
        checkIn.setOnClickListener(onSmartCardCheckIn); ///-----------------1

        Button dailySummary = (Button) findViewById(R.id.btDailySummary);
        dailySummary.setOnClickListener(onDailySummary);///-----------------2

        Button topUp = (Button) findViewById(R.id.btTopUp);
        topUp.setOnClickListener(onTopUp);              ///-----------------3

        Button noCard = (Button) findViewById(R.id.check_in_button_no_card);
        noCard.setOnClickListener(onCashCheckIn);       ///-----------------4

        Button noCardMultiple = (Button) findViewById(R.id.main_multiple_checkin);
        noCardMultiple.setOnClickListener(onMultipleCashCheckIn);///-----------------5

        Button btnRefund = (Button) findViewById(R.id.main_refund);
        btnRefund.setOnClickListener(new View.OnClickListener() ///-----------------6
        {
            @Override
            public void onClick(View view)
            {
                if (WorkingSession.getInstance().lastCashTransaction != null &&
                        Utilities.DateDifferenceSecond(new Date(), WorkingSession.getInstance().lastCashTransaction) < 2)
                {
                    Log.e(TAG, "Opps, I cannot process multiple submit at same time");
                    return;
                }
                //--
                //if(WorkingSession.getInstance().currentActivity == Main.this)
                //Toast.makeText(Main.this, "True", Toast.LENGTH_SHORT).show();
                //else
                //  Toast.makeText(Main.this, "false", Toast.LENGTH_SHORT).show();
                int x = doEnsurePassengerInfo(true);
                if (x == -1) //invalid customer id
                {
                    ShowInvalidCard();
                    return;
                }
                else if (x == -2) //no customer id input
                {
                    lastRequest = Declarations.REQUEST_MAIN_REFUND;
                    ShowWaitCardDialog(true);
                    return;
                }

                Intent Int = new Intent(Main.this, refund.class);
                startActivityForResult(Int, Declarations.REQUEST_REFUND);
            }
        });


        Button checkcustid = (Button) findViewById(R.id.btCheckID);
        checkcustid.setOnClickListener(onCheckCustID);

        Button clearcustid = (Button) findViewById(R.id.btClear);
        clearcustid.setOnClickListener(onClearID);

        fillCustomerData();

//		nfcAdapter = NfcAdapter.getDefaultAdapter(this);
//		mPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this,
//				getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);

        //onNewIntent(getIntent());

        EditText tmp = (EditText) findViewById(R.id.edtCustomerID);
        getWindow().setSoftInputMode(
                WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
        ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE))
                .hideSoftInputFromWindow(tmp.getWindowToken(), 0);
        //--
        Button btnSetting = (Button) findViewById(R.id.main_btn_setting);
        btnSetting.setOnClickListener(new View.OnClickListener()
        {

            @Override
            public void onClick(View v)
            {
                Intent Int = new Intent(Main.this, Settings.class);
                startActivity(Int);
                //startActivityForResult(Int, REQUEST_CONNECT_DEVICE);
            }
        });

        //----Nov.27.2014 by lhdung
        UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);

        HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
        if (deviceList.isEmpty())
        {
//            WorkingSession.getInstance().ShowErrorDialog(
//                    this,
//                    "Warning",
//                    "Please connect card reader"
//                                                        );
            WorkingSession.getInstance().ShowToast(
                    this,
                    "Please connect card reader",
                    Toast.LENGTH_LONG
                                                  );
        }

    }

    //======================================================================================================================
//    private final class ThreadHandlerTapCard extends Handler
//    {
//        private final String TAG = "ThreadHandlerTapCard";
//
//        public ThreadHandlerTapCard(Looper lp)
//        {
//            super(lp);
//        }
//
//        //public ThreadHandlerTapCard(){
//        //   super();
//        //}
//        //Intent input = new Intent(Main.this, CheckInV2Stage.class);
//        String LogicalNumber = "";
//        String CardSerial = "";
//
//        @Override
//        public void handleMessage(final Message msg)
//        {
//            //super.handleMessage(msg);
//
//            switch (msg.arg1)
//            {
//                case 1:
//                    Log.d(TAG, "[ThreadHandlerTapCard.handleMessage] Case 1");
//                    if (lastRequest == 0 && WorkingSession.getInstance().currentActivity == Main.this)
//                    {
//                        NfcCardInfo info = WorkingSession.getInstance().SAMGetCardBalance();
//                        LogicalNumber = info.CardIssuer.LogicalNumber.toString();
//                        LogicalNumber = LogicalNumber.substring(LogicalNumber.length() - 8);
//                        CardSerial = info.CardIssuer.Serial.toString();
//                        //--
//                        Log.d(TAG, "[ThreadHandlerTapCard.handleMessage] Tapin - Auto check in");
//                        runOnUiThread(new Runnable()
//                        {
//                            @Override
//                            public void run()
//                            {
//                                doTapInOut(CardSerial, LogicalNumber);
//
//                            }
//                        });
//                    }
//                    break;
//
//                case 0:
//                    Log.d("Tapout", "Leave card reader");
//                    break;
//            }
//        }
//
//        // TO DO SOMETHINGS AT HERE
//        public Message CreateShowToastMsg(String str)
//        {
//            Message msgTemp = new Message();
//
//            return msgTemp;
//        }
//
//        // TO DO SOMETHINGS AT HERE
//        public Message CreateShowAlertDialogMsg(String dialogTitle, String content)
//        {
//            Message mgs = new Message();
//
//            return mgs;
//        }
//    }

    //====================================================================================================================
    //private int cardSlot;
    //private string SmartCardType;


//    public void doGetSmartCardInfo()
//    {
//        Log.d(TAG, "[doGetSmartCardInfo] ....");
//        WorkingSession.getInstance().OpenSAMCardReader(cardSlot);
//        new Thread(GetCardBalance).start();
//    }

    public boolean WaitCardReaderOpenAndTapped()
    {
        Log.d(TAG, "[WaitCardReaderOpenAndTapped] Waiting for card tapped in 10s...");
        Date lastTest = new Date();
        long diffInSec = 0;
        try
        {
            do
            {
                Thread.sleep(200);
                long diffInMs = (new Date()).getTime() - lastTest.getTime();
                diffInSec = TimeUnit.MILLISECONDS.toSeconds(diffInMs);
                lastTest = new Date();
            }
            while (!WorkingSession.getInstance().IsSmartCardTapped() && diffInSec < 10); //waiting for 10s
        }
        catch (Exception ex)
        {
            Log.e(TAG, "[WaitCardReaderOpenAndTapped] Exception: " + ex);
            ex.printStackTrace();
            return false;
        }
        if (diffInSec >= 10)
            return false;
        return true;
    }


//    private Runnable GetCardBalance = new Runnable()
//    {
//        @Override
//        public void run()
//        {
////            try {
////                int x = WorkingSession.getInstance().getSAM_NfcCardTapped();
////                while ( x != 1) {
////                    Thread.sleep(100);
////                    x = WorkingSession.getInstance().getSAM_NfcCardTapped();
////                }
////            }
////            catch (Exception ex)
////            {
////                return;
////            }
//            Log.d(TAG, "[GetCardBalance] Get card balance...");
//            NfcCardInfo info = WorkingSession.getInstance().SAMGetCardBalance();
//            //cardReader.Dispose();
//            if (info != null)
//            {
//                Log.d(TAG, "[GetCardBalance] balance: " + info.Balance);
//                Log.d(TAG, "[GetCardBalance] card Issuer: " + info.CardIssuer.toString());
//                //--
//                Intent x = new Intent();
//                x.putExtra("RESULT_TAG_SERIAL", info.CardIssuer.Serial);
//                x.putExtra("RESULT_TAG_CARD_NUMBER", info.CardIssuer.LogicalNumber);
//                x.putExtra("RESULT_TAG_BALANCE", info.Balance);
//                x.putExtra("RESULT_TAG_SAM_CARD_SLOT", cardSlot);
//
//                setResult(RESULT_OK, x);
//                finish();
//            }
//        }
//    };

    //--------------------------------------------------------------------------------------------------------
    private void doLogOut()
    {
        WorkingSession.getInstance().Reset();
        //--
        Intent loginIntent = new Intent(getApplicationContext(),
                                        SunBeamStartUp.class);
        //loginIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(loginIntent);
        finish();
    }


    //------------------------------------------------------------------------------------------------------------------


    //------------------------------------------------------------------------------------------------------------------
    private void doRestartApp()
    {
        WorkingSession.getInstance().ShowToast(Main.this, "Restarting...", LENGTH_SHORT);
        WorkingSession.getInstance().SaveCurrentSession(Main.this);
        //--
        try
        {
            //--
            Intent i = getBaseContext().getPackageManager()
                    .getLaunchIntentForPackage(getBaseContext().getPackageName());
            i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            //--
            AlarmManager alm = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
            alm.set(
                    AlarmManager.RTC,
                    System.currentTimeMillis() + 1000,
                    PendingIntent.getActivity(Main.this, 0, i, PendingIntent.FLAG_CANCEL_CURRENT));
            //--
            finish();
            android.os.Process.killProcess(android.os.Process.myPid());
        }
        catch (Exception ex)
        {
            Log.e(TAG, "[onStart] Kill process Exception: " + ex.toString());
            ex.printStackTrace();
        }
    }

    private boolean checkDoLogOut()
    {
        Intent input = getIntent();
        int logout = input.getIntExtra("LOG_OUT", 0);
        input.putExtra("LOG_OUT", 0);//prevent loop
        if (logout == 1)
            return true;
        return false;
    }

    @Override
    public void onStart()
    {

        Log.d(TAG, "[onStart] ....");
        super.onStart();

        UpdateBottomLine();

        //--checking for automatically restart
        if (WorkingSession.getInstance().isNeedToRestart())
        {
            Log.d(TAG, "[onStart] Restarting...");
            doRestartApp();
            return;
        }

        //---
        Button clearCustomerId = (Button) findViewById(R.id.btClear);
        clearCustomerId.performClick();

/*
        if(!WorkingSession.getInstance().checkAndEnableBluetooth(this))
            finish();
*/
        if (checkDoLogOut())
        {
            Log.d(TAG, "[onStart] Logging out...");
            doLogOut();

            return;
        }
        //--
        Intent input = getIntent();
        String inputCustomer = input.getStringExtra("INPUT_CUSTOMER");
        int directCheckIn = input.getIntExtra("INPUT_DIRECT_CHECK_IN", 0);
        //--clear input data
        input.putExtra("INPUT_CUSTOMER", "");
        input.putExtra("INPUT_DIRECT_CHECK_IN", 0);
        //--
        if (directCheckIn == 1) //go to Cash check in
        {
            Log.d(TAG, "[onStart] go No Card Check-In");
            onCashCheckIn.onClick(null);
        }
        else if (inputCustomer != null && inputCustomer.length() > 0)
        {
            boolean newSwipe = false;
            if (inputCustomer.startsWith("++"))
            {
                newSwipe = true;
                inputCustomer = inputCustomer.substring(2);
            }
            MemberValue cust = db.getMemberByCard(inputCustomer);

            if (cust != null)
            {
                WorkingSession.getInstance().currentPassenger = cust;

                EditText customerID = (EditText) findViewById(R.id.edtCustomerID);
                customerID.setText(cust.CardNumber);

                TextView customerName = (TextView) findViewById(R.id.tvCustName);
                customerName.setTextColor(Color.rgb(0, 0, 0));
                customerName.setText(cust.getFullName());

                TransactionValue xx = db.getLastCheckInTransaction(
                        cust.ISN,
                        WorkingSession.getInstance().journalRoute.ISN,
                        WorkingSession.getInstance().journalBus.ISN);
                if (xx != null)
                {
                    Intent checkOut = new Intent(Main.this, CheckInV2TapOut.class);
                    startActivity(checkOut);
                }
                else if (newSwipe)
                {
                    input = new Intent(Main.this, CheckInV2TapIn.class);
                    startActivity(input);
                }
                else
                {
                    Intent checkIn = new Intent(Main.this, CheckInV2Stage.class);
                    checkIn.putExtra("CHECK-IN_TYPE", Declarations.CHECK_IN_TYPE_TAP_IN);
                    startActivity(checkIn);
                }
            }
        }
    }

    @Override
    protected void onResume()
    {
        Log.d(TAG, "[onResume] ....");
        super.onResume();
//		if (nfcAdapter != null)
//		{
//			nfcAdapter.enableForegroundDispatch(this, mPendingIntent, null, null);
//			// mAdapter.enableForegroundNdefPush(this);
//		}

        //--checking for automatically restart
        if (WorkingSession.getInstance().isNeedToRestart())
        {
            try
            {
                Log.d(TAG, "[onResume] Restarting...");
                doRestartApp();
                return;
            }
            catch (Exception ex)
            {
                Log.e(TAG, "[onResume] Kill process Exception: " + ex.toString());
                ex.printStackTrace();
            }
        }
        //--
        if (checkDoLogOut())
        {
            Log.d(TAG, "[onResume] Logging out...");
            doLogOut();

            return;
        }
        //--
        Intent input = getIntent();
        int directCheckIn = input.getIntExtra("INPUT_DIRECT_CHECK_IN", 0);
        //--clear input data
        input.putExtra("INPUT_CUSTOMER", "");
        input.putExtra("INPUT_DIRECT_CHECK_IN", 0);
        //--
        if (directCheckIn == 1) //go to no Cash check in
        {
            Log.d(TAG, "[onResume] go No Card Check-In");
            onCashCheckIn.onClick(null);
        }
    }

    @Override
    protected void onPause()
    {
        Log.d(TAG, "[onPause] ....");
        super.onPause();
//		if (nfcAdapter != null)
//		{
//			nfcAdapter.disableForegroundDispatch(this);
//			//nfcAdapter.disableForegroundNdefPush(this);
//            nfcAdapter.setNdefPushMessage(null, this);
//		}
    }

    @Override
    protected void onDestroy()
    {
        Log.d(TAG, "[onDestroy] ....");
        super.onDestroy();
        Main.theInstance = null;
/*
        WorkingSession.getInstance().StopBluetoothService();*/
    }

//	@Override
//	public void onNewIntent(Intent intent)
//	{
//        String action = intent.getAction();
//        Log.d(TAG, String.format("[onNewIntent] Action: %s", action));
//
//        if (action != null && (action.equals(NfcAdapter.ACTION_TAG_DISCOVERED)
//                || action.equals(NfcAdapter.ACTION_NDEF_DISCOVERED)))
//        {
//            //setIntent(intent);
//
//            ProcessNFCIncome(intent);
//        }
//	}

//	private void ProcessNFCIncome(Intent intent)
//	{
//		String[] result = Utilities.readNFCTagContentAndSerial(Main.this, intent);
//        //--result[0] = TagSerial, result[1] = Tag content
//        if (result == null || result.length < 2)
//            return;
//
//        if(result[1].length() == 0)
//            WorkingSession.getInstance().ShowErrorDialog(Main.this, "Error", "Invalid NFC Tag content");
////
//        doTapInOut(result[0], result[1]);
//	}


    private void doTapInOut(String tagSerial, String tagContent)
    {
        Log.d(TAG, "[doTapInOut]...");
        EditText customerID = (EditText) findViewById(R.id.edtCustomerID);
        customerID.setText(tagContent);

        TextView customerName = (TextView) findViewById(R.id.tvCustName);
        customerName.setText("");

        MemberValue cust = db.getMemberByCard(tagContent, tagSerial);

        if (cust != null)
        {
            WorkingSession.getInstance().currentPassenger = cust;

            customerName.setTextColor(Color.rgb(0, 0, 0));
            customerName.setText(cust.getFullName());

            TransactionValue xx = db.getLastCheckInTransaction(
                    cust.ISN,
                    WorkingSession.getInstance().journalRoute.ISN,
                    WorkingSession.getInstance().journalBus.ISN);
            if (xx != null)
            {
                Intent input = new Intent(Main.this, CheckInV2TapOut.class);
                startActivity(input);
                //doRecordCheckIn();
            }
            else
            {
                Intent input = new Intent(Main.this, CheckInV2TapIn.class);
                //input.putExtra("CHECK-IN_TYPE", Declarations.CHECK_IN_TYPE_TAP_IN);
                startActivity(input);
                //doRecordCheckOut();
            }
        }
        else
        {
            ShowInvalidCard();
        }
    }

    private void fillCustomerData()
    {
        EditText tmp = (EditText) findViewById(R.id.edtCustomerID);
        tmp.setHint(Html.fromHtml("<small><small><small>Last 8 digits of card number</small></small></small>"));
        //--
        TextView tvtmp = (TextView) findViewById(R.id.tvCustName);

        if (WorkingSession.getInstance().currentPassenger == null)
        {
            tmp.setText("");
            tvtmp.setText("");
        }
        else
        {
            tmp.setText(WorkingSession.getInstance().currentPassenger.CardNumber);
            //--
            tvtmp.setTextColor(Color.rgb(0, 0, 0));
            tvtmp.setText(WorkingSession.getInstance().currentPassenger.getFullName());
        }
    }

    private void ShowInvalidCard()
    {
        TextView customerName = (TextView) findViewById(R.id.tvCustName);
        customerName.setTextColor(Color.rgb(255, 0, 0));
        customerName.setText("Invalid Card");

    }

    private void ShowInvalidCard(String textContent)
    {
        TextView customerName = (TextView) findViewById(R.id.tvCustName);
        customerName.setTextColor(Color.rgb(255, 0, 0));
        customerName.setText(textContent);

    }

    public void onActivityResult(int requestCode, int resultCode, Intent intent)
    {

        switch (requestCode)
        {
            case 0:
                if (resultCode == RESULT_OK)
                {
                    String contents = intent.getStringExtra("SCAN_RESULT");
                    // String format = intent.getStringExtra("SCAN_RESULT_FORMAT");
                    EditText custid = (EditText) findViewById(R.id.edtCustomerID);
                    custid.setText(contents);

                }
                else if (resultCode == RESULT_CANCELED)
                {
                    WorkingSession.getInstance().ShowToast(Main.this, "Unable scan QR Code",
                                                           LENGTH_SHORT);
                }
                break;

            case Declarations.REQUEST_WAIT_TAG:

                if (resultCode == Activity.RESULT_OK)
                {
                    int option = intent.getIntExtra("RESULT_OPTION_ENTER_ID", 0);
                    String serial = intent.getStringExtra("RESULT_TAG_SERIAL");
                    String cardNumber = intent.getStringExtra("RESULT_TAG_CARD_NUMBER");
                    int cardBalance = intent.getIntExtra("RESULT_TAG_BALANCE", 0);
                    Enums.CardProvider cardType  = Enums.CardProvider.values()[intent.getIntExtra("RESULT_TAG_SAM_CARD_SLOT",
                        Enums.CardProvider.BMF.getValue())];
                    //--
                    doPendingCommand(serial, cardNumber, cardBalance, option, cardType);

                    //--
                }

                //lastRequest = 0;
                break;
        }
    }

    private void doPendingCommand(String tagSerial,
                                  String cardNumber,
                                  int cardBalance,
                                  int byCardId,
                                  Enums.CardProvider cardProvider)
    {
        Log.d(TAG, String.format("[doPendingCommand] Card serial %s, card number %s, current card balance %d",
                                 tagSerial, cardNumber, cardBalance));
        TextView customerName = (TextView) findViewById(R.id.tvCustName);
        customerName.setText("");

        Log.d(TAG, "[doPendingCommand] Extract card number...");
        cardNumber = cardNumber.length() > 8 ? cardNumber.substring(cardNumber.length() - 8) : cardNumber;
        Log.d(TAG, "[doPendingCommand] Final card number: " + cardNumber);
        EditText customerID = (EditText) findViewById(R.id.edtCustomerID);
        customerID.setText(cardNumber);
        Log.d(TAG, String.format("[doPendingCommand] Get member by card info db.getMemberByCard('%s', '%s');",
                                 cardNumber, tagSerial));
        MemberValue cust = db.getMemberByCard(cardNumber, tagSerial);

        if (cust == null)
        {
            ShowInvalidCard();
            return;
        }

        Log.d(TAG, "[doPendingCommand] Found customer with name: " + cust.getFullName());
        customerName.setTextColor(Color.rgb(0, 0, 0));
        customerName.setText(cust.getFullName());
        //--
        Log.d(TAG, "[doPendingCommand] set WorkingSession.getInstance().currentPassenger = cust;");
        WorkingSession.getInstance().currentPassenger = cust;
        //---
        Log.d(TAG, "[doPendingCommand] Get current GPS location...");
        GpsCurrentLocationValue currentGpsLocation = gpsDb.getCurrentLocation(
                WorkingSession.getInstance().setupJournal.ISN);
        if(currentGpsLocation == null)
            Log.d(TAG, "[doPendingCommand] Unable to get current GPS location");
        else
            Log.d(TAG, "[doPendingCommand] " + currentGpsLocation.toString());

        int intMemBalance = (int)(cust.CurrentBalance*100);
        Log.d(TAG, String.format("[doPendingCommand] compare account current balance %d vs card balance %d",
                intMemBalance, cardBalance));
        if (intMemBalance != cardBalance)
        {
            Log.d(TAG, "[doPendingCommand] Preparing to update account balance to card...");
            WaitCardReaderOpenAndTapped();
            if (WorkingSession.getInstance().IsCardReaderOpened() &&
                    WorkingSession.getInstance().IsSmartCardTapped())
            {
                Log.d(TAG, "[doPendingCommand] Updating account balance to card...");
                if (!WorkingSession.getInstance().SAMUpdateCardBalance(
                        cardProvider,
                        intMemBalance,
                        currentGpsLocation != null ? (float) currentGpsLocation.Latitude : 0,
                        currentGpsLocation != null ? (float) currentGpsLocation.Longitude : 0))
                {
                    WorkingSession.getInstance().ShowErrorDialog(
                            Main.this,
                            "Error",
                            "Unable to update card's balance"
                                                                );
                }
            }
        }

        TransactionValue xx = db.getLastCheckInTransaction(
                cust.ISN,
                WorkingSession.getInstance().journalRoute.ISN,
                WorkingSession.getInstance().journalBus.ISN);
        if (xx != null)
        {
            Intent checkOut = new Intent(Main.this, CheckInV2TapOut.class);
            startActivity(checkOut);
            return;
        }

        if (lastRequest == Declarations.REQUEST_MAIN_REFUND)
        {
            Intent input = new Intent(Main.this, refund.class);
            if (byCardId == 1)
                input.putExtra("OPTION_NO_CARD", 1);
            startActivityForResult(input, Declarations.REQUEST_REFUND);
            return;
        }
        else if (lastRequest == Declarations.REQUEST_MAIN_CHECK_IN)
        {
            Intent input = new Intent(Main.this, CheckInV2Stage.class);
            input.putExtra("CHECK-IN_TYPE", Declarations.CHECK_IN_TYPE_NORMAL);
            startActivity(input);
            //lastRequest = Declarations.REQUEST_MAIN_CHECK_IN;
        }
        else if (lastRequest == Declarations.REQUEST_MAIN_TOP_UP)
        {
            Log.d(TAG, "Start BMF Top Up...");
            Intent Int = new Intent(Main.this, TopUp.class);
            startActivity(Int);
            //lastRequest = Declarations.REQUEST_MAIN_TOP_UP;
        }
        else
        {
            Intent input = new Intent(Main.this, CheckInV2TapIn.class);
            input.putExtra("CHECK-IN_TYPE", Declarations.CHECK_IN_TYPE_NORMAL);
            startActivity(input);
        }
    }


    View.OnClickListener onClearID = new View.OnClickListener()
    {

        @Override
        public void onClick(View v)
        {
            EditText tmp = (EditText) findViewById(R.id.edtCustomerID);
            tmp.setText("");

            TextView tvtmp = (TextView) findViewById(R.id.tvCustName);
            tvtmp.setText("");
        }
    };

    ///return -1: invalid customer id, -2: no customer id
    private int doEnsurePassengerInfo(boolean requireCardNo)
    {
        EditText customerID = (EditText) findViewById(R.id.edtCustomerID);
        String cardNumber = customerID.getText().toString().trim();
        //---
        MemberValue cust;

        if (cardNumber.length() == 0)
        {
            if (!requireCardNo)
                cardNumber = db.getRuntimeValues("defaultCard");
            else
            {
                //ShowInvalidCard("Please enter Customer ID");
                return -2;
            }
        }
        cust = db.getMemberByCard(cardNumber);

        if (cust != null)
        {
            WorkingSession.getInstance().currentPassenger = cust;
            if (requireCardNo)
                fillCustomerData();

            return 0;
        }

        return -1;
    }

    View.OnClickListener onSmartCardCheckIn = new View.OnClickListener()
    {
        @Override
        public void onClick(View v)
        {
            if (WorkingSession.getInstance().lastCashTransaction != null &&
                    Utilities.DateDifferenceSecond(new Date(), WorkingSession.getInstance().lastCashTransaction) < 2)
            {
                Log.e(TAG, "You're submitting too fast. Please slow down");
                return;
            }
            //--


            int x = doEnsurePassengerInfo(true);
            if (x == -1)
            {
                ShowInvalidCard();
                return;
            }
            else if (x == -2)
            {
                //ShowInvalidCard("Please enter last 8 Digit Card Number");
                lastRequest = Declarations.REQUEST_MAIN_CHECK_IN;
                ShowWaitCardDialog(false);
                return;
            }

            Intent input = new Intent(Main.this, CheckInV2Stage.class);
            input.putExtra("CHECK-IN_TYPE", Declarations.CHECK_IN_TYPE_NORMAL);
            startActivity(input);
        }
    };

    View.OnClickListener onDailySummary = new View.OnClickListener()
    {

        @Override
        public void onClick(View v)
        {

            if (WorkingSession.getInstance().lastCashTransaction != null &&
                    Utilities.DateDifferenceSecond(new Date(), WorkingSession.getInstance().lastCashTransaction) < 2)
            {
                Log.e(TAG, "You're submitting too fast. Please slow down");
                return;
            }
            /*int x = doEnsurePassengerInfo(false);
            if(x == -1)
            {
                ShowInvalidCard();
                return;
            }*/

            //Toast.makeText(Main.this,Integer.toString(lastRequest), Toast.LENGTH_SHORT).show();
            //--
            // lastRequest = 1;
            Intent Int = new Intent(Main.this, DailySummary.class);
            startActivity(Int);
        }
    };

    View.OnClickListener onTopUp = new View.OnClickListener()
    {

        @Override
        public void onClick(View v)
        {

            // lastRequest = 1;
            if (WorkingSession.getInstance().lastCashTransaction != null &&
                    Utilities.DateDifferenceSecond(new Date(), WorkingSession.getInstance().lastCashTransaction) < 2)
            {
                Log.e(TAG, "You're submitting too fast. Please slow down");
                return;
            }
            //--

            //Toast.makeText(Main.this,Integer.toString(lastRequest), Toast.LENGTH_SHORT).show();
            int x = doEnsurePassengerInfo(true);
            if (x == -1)
            {
                ShowInvalidCard();
                return;
            }
            else if (x == -2)
            {
                lastRequest = Declarations.REQUEST_MAIN_TOP_UP;
                ShowWaitCardDialog(false);
                return;
            }
            //--
            Intent Int = new Intent(Main.this, TopUp.class);
            startActivity(Int);
        }
    };

    View.OnClickListener onCashCheckIn = new View.OnClickListener()
    {
        @Override
        public void onClick(View v)
        {

            //lastRequest = 1;

            try
            {
                if (v != null && WorkingSession.getInstance().lastCashTransaction != null &&
                        Utilities.DateDifferenceSecond(new Date(), WorkingSession.getInstance().lastCashTransaction) < 2)
                {
                    Log.e(TAG, "You're submitting too fast. Please slow down");
                    return;
                }
                //--

                Log.d(TAG, "[onCashCheckIn]...");
                int x = doEnsurePassengerInfo(false);
                //Log.d(TAG, "[onCashCheckIn] 1111");
                if (x == -1)
                {
                    ShowInvalidCard();
                    return;
                }
                //--

                int stageCount = db.getStageCountOfRoute(WorkingSession.getInstance().journalRoute.ISN);

                Main.this.lastRequest = Declarations.REQUEST_MAIN_NO_CARD_CHECK_IN;
                Intent input = null;
                if (stageCount <= 3)
                    input = new Intent(Main.this, CheckInV2Cash.class);
                else
                    input = new Intent(Main.this, CheckInV2Cash_4more.class);
                //input.putExtra("CHECK-IN_TYPE", Declarations.CHECK_IN_TYPE_NO_CARD);
                startActivity(input);
                //Log.d(TAG, "[onCashCheckIn] 222");
            }
            catch (Exception ex)
            {
                Log.e(TAG, "[onCashCheckIn.Click] EXCEPTION: " + ex.toString());
                ex.printStackTrace();
            }
        }
    };

    View.OnClickListener onMultipleCashCheckIn = new View.OnClickListener()
    {
        @Override
        public void onClick(View v)
        {

            // lastRequest = 1;
            if (WorkingSession.getInstance().lastCashTransaction != null &&
                    Utilities.DateDifferenceSecond(new Date(), WorkingSession.getInstance().lastCashTransaction) < 2)
            {
                Log.e(TAG, "You're submitting too fast. Please slow down");
                return;
            }
            //--

            Log.d(TAG, "[onMultipleCashCheckIn]...");
            int x = doEnsurePassengerInfo(false);
            //Log.d(TAG, "[onCashCheckIn] 1111");
            if (x == -1)
            {
                ShowInvalidCard();
                return;
            }
            //--
            //Intent input = new Intent(Main.this, CheckInV2Stage.class);
            Main.this.lastRequest = Declarations.REQUEST_MAIN_NO_CARD_CHECK_IN;
            Intent input = new Intent(Main.this, CheckInV2CashMultiple.class);
            //input.putExtra("CHECK-IN_TYPE", Declarations.CHECK_IN_TYPE_NO_CARD);
            startActivity(input);
            //Log.d(TAG, "[onCashCheckIn] 222");
        }
    };

	/*View.OnClickListener onBoardPassenger = new View.OnClickListener()
    {

		@Override
		public void onClick(View v)
		{
			Intent Int = new Intent(Main.this, OnboardPassenger.class);
			startActivity(Int);
		}
	};*/

    View.OnClickListener onCheckCustID = new View.OnClickListener()
    {

        @Override
        public void onClick(View v)
        {
            InputMethodManager inputManager = (InputMethodManager)
                    getSystemService(Context.INPUT_METHOD_SERVICE);

            inputManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(),
                                                 InputMethodManager.HIDE_NOT_ALWAYS);
            //---
            TextView tvtmp = (TextView) findViewById(R.id.tvCustName);
            tvtmp.setText("");

            EditText tmp = (EditText) findViewById(R.id.edtCustomerID);

            if (tmp.getText().toString().trim().equals(""))
            {
                ShowInvalidCard("Please enter last 8 digits of Card");
                return;
            }

            int x = doEnsurePassengerInfo(true);
            if (x == -1 || x == -2)
            {
                ShowInvalidCard();
                return;
            }

            Intent input = new Intent(Main.this, CheckInV2Stage.class);
            input.putExtra("CHECK-IN_TYPE", Declarations.CHECK_IN_TYPE_NORMAL);
            startActivity(input);
        }
    };

    private void ShowWaitCardDialog(boolean withId)
    {
        Intent x = new Intent(Main.this, HomeWaitCard.class);
        if (withId)
        {
            x.putExtra("WAIT_OPTION", 1);
        }
        startActivityForResult(x, Declarations.REQUEST_WAIT_TAG);
    }

    //added by lhdung Nov.2014
    private WorkingSession.SAMReaderEvent samReaderEvent = new WorkingSession.SAMReaderEvent()
    {
        @Override
        public void OnReaderStateChange(String state)
        {
            Log.d(TAG, "[SAMReaderEvent.OnReaderStateChange] " + state);
            WorkingSession.getInstance().ShowToast(
                    Main.this,
                    "Card Reader " + state,
                    Toast.LENGTH_SHORT
                                                  );
        }

        @Override
        public void OnSAMSlotStateChange(int slot, String state)
        {
            Log.d(TAG, String.format("[SAMReaderEvent.OnSAMSlotStateChange] Slot  %d state %s", slot, state));

        }

        @Override
        public void OnSmartCardInteraction(Enums.CardProvider cardProvider, int status, String description)
        {

            if (status == Declarations.SMART_CARD_STATE_PRESENT) //tap in
            {
                Log.d(TAG, String.format("[SAMReaderEvent.OnSmartCardInteraction] %s tapped. Card status  %d, %s",
                        cardProvider.toString(), status, description));
                //do process tap in
                tappedCardType = cardProvider;
                theHandler.post(doProcessCardTapped);
            }
            else //may be tap out
            {
                Log.d(TAG, String.format("[SAMReaderEvent.OnSmartCardInteraction] %s removed. Card status  %d, %s",
                        cardProvider.toString(), status, description));
            }
        }
    };

    private Enums.CardProvider tappedCardType;
    private Runnable doProcessCardTapped = new Runnable()
    {
        @Override
        public void run()
        {
            Log.d(TAG, "[doProcessCardTapped] Get Card information...");
            NfcCardInfo info = WorkingSession.getInstance().SAMGetCardBalance(tappedCardType);
            if(info == null)
            {
                Log.d(TAG, "[doProcessCardTapped] Unable get smart card info");
                return;
            }

            if(WorkingSession.getInstance().currentActivity != Main.this)
            {
                WorkingSession.getInstance().currentActivity.finish();
                WorkingSession.getInstance().currentActivity = Main.this;
            }

            doPendingCommand(
                    info.CardIssuer.Serial,
                    info.CardIssuer.LogicalNumber,
                    info.Balance,
                    0,
                    tappedCardType);
        }
    };

}
